#include "raylib.h"
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <assert.h>

// 游戏配置常量
#define BOARD_SIZE 11 // 棋盘大小(8-11)
static_assert(BOARD_SIZE <= 11 && BOARD_SIZE >= 8, "game board must be range from 8 to 11");
#define TILE_SIZE 60         // 格子大小
#define TILE_TYPES 5         // 字符类型数量
#define FONT_SIZE 32         // 字体大小
#define FALL_SPEED 18.0f     // 下落速度
#define SCORE_PER_PAIR 5     // 每对分数
#define MENU_WIDTH 240       // 设置菜单宽度
#define MENU_HEIGHT 360      // 设置菜单高度
#define MAX_BACKGROUNDS 3    // 最大背景数量
#define MAX_SOUNDS 3         // 最大音效变体数量
#define MAX_GEN_ATTEMPTS 100 // 生成字符的最大尝试次数(避免死循环)

// 编译时验证
static_assert(TILE_SIZE > 42 && TILE_SIZE < 80, "格子大小必须在42-80之间");
static_assert(FONT_SIZE > 20 && FONT_SIZE < 40, "字体大小必须在20-40之间");

// 可匹配的字符集合
const char tile_chars[TILE_TYPES] = {'#', '@', '$', '%', '&'};

// 资源路径
const char *bg_paths[MAX_BACKGROUNDS] = {
    "./bg.png", "./bg2.png", "./bg3.png"};

const char *swap_sound_paths[MAX_SOUNDS] = {
    "./kling.wav", "./killdeer.wav", "./ok.wav"};

const char *match_sound_paths[MAX_SOUNDS] = {
    "./kling.wav", "./killdeer.wav", "./ok.wav"};

const char *click_sound_paths[MAX_SOUNDS] = {
    "./kling.wav", "./killdeer.wav", "./ok.wav"};

// 游戏状态结构体
typedef struct
{
    char board[BOARD_SIZE][BOARD_SIZE];         // 棋盘数据
    bool matched_board[BOARD_SIZE][BOARD_SIZE]; // 匹配标记
    float fall_offset[BOARD_SIZE][BOARD_SIZE];  // 下落偏移量
    Vector2 grid_origin;                        // 棋盘原点
    int score;                                  // 分数
    Vector2 selected_tile;                      // 选中的格子
    Vector2 preview_tile;                       // 预览交换的格子
    bool is_previewing;                         // 交换预览状态
    bool sound_enabled;                         // 声音开关
    bool show_settings;                         // 显示设置菜单
    bool should_exit;                           // New: Exit flag
    int max_chain_depth;                        // 最大连锁深度限制
    int current_chain_depth;                    // 当前连锁深度

    // 资源管理
    Texture2D backgrounds[MAX_BACKGROUNDS]; // 背景数组
    int current_bg;                         // 当前背景索引
    Sound swaps[MAX_SOUNDS];                // 交换音效
    Sound matches[MAX_SOUNDS];              // 匹配音效
    Sound clicks[MAX_SOUNDS];               // 点击音效
    int current_sound_variation;            // 音效变体索引
    Font game_font;                         // 字体
} GameState;

// 初始化游戏状态
void init_game(GameState *game, int screen_width, int screen_height)
{
    // 填充随机字符
    for (int y = 0; y < BOARD_SIZE; y++)
    {
        for (int x = 0; x < BOARD_SIZE; x++)
        {
            game->board[y][x] = tile_chars[rand() % TILE_TYPES];
        }
    }

    // 计算棋盘居中位置
    int grid_width = BOARD_SIZE * TILE_SIZE;
    int grid_height = BOARD_SIZE * TILE_SIZE;
    game->grid_origin = (Vector2){
        (screen_width - grid_width) / 2.0f,
        (screen_height - grid_height) / 2.0f};

    // 初始化核心状态（新增连锁深度控制）
    game->score = 0;
    game->selected_tile = (Vector2){-1, -1};
    game->preview_tile = (Vector2){-1, -1};
    game->is_previewing = false;
    game->sound_enabled = true;
    game->show_settings = false;
    game->should_exit = false; // Initialize exit flag
    game->current_bg = 0;
    game->current_sound_variation = 0;
    game->max_chain_depth = 3; // 最大连锁深度（可调整，如3次连锁后停止）
    game->current_chain_depth = 0;
    memset(game->matched_board, 0, sizeof(game->matched_board));
    memset(game->fall_offset, 0, sizeof(game->fall_offset));

    // 加载资源
    for (int i = 0; i < MAX_BACKGROUNDS; i++)
    {
        game->backgrounds[i] = LoadTexture(bg_paths[i]);
        if (game->backgrounds[i].id == 0)
            TraceLog(LOG_WARNING, "背景资源 %s 加载失败", bg_paths[i]);
    }

    game->game_font = LoadFontEx("./Tuffy.ttf", FONT_SIZE, NULL, 0);
    if (game->game_font.baseSize == 0)
    {
        TraceLog(LOG_WARNING, "Tuffy.ttf 未找到，使用默认字体");
        game->game_font = GetFontDefault();
    }

    for (int i = 0; i < MAX_SOUNDS; i++)
    {
        game->swaps[i] = LoadSound(swap_sound_paths[i]);
        game->matches[i] = LoadSound(match_sound_paths[i]);
        game->clicks[i] = LoadSound(click_sound_paths[i]);
    }

    // 确保初始无匹配
    bool has_initial_match;
    do
    {
        has_initial_match = false;
        for (int y = 0; y < BOARD_SIZE; y++)
        {
            for (int x = 0; x < BOARD_SIZE - 1; x++)
            {
                if (game->board[y][x] == game->board[y][x + 1])
                {
                    game->board[y][x] = tile_chars[rand() % TILE_TYPES];
                    has_initial_match = true;
                }
            }
        }
        for (int x = 0; x < BOARD_SIZE; x++)
        {
            for (int y = 0; y < BOARD_SIZE - 1; y++)
            {
                if (game->board[y][x] == game->board[y + 1][x])
                {
                    game->board[y][x] = tile_chars[rand() % TILE_TYPES];
                    has_initial_match = true;
                }
            }
        }
    } while (has_initial_match);
}

// 播放音效
void play_sound(GameState *game, Sound *sounds, bool enabled)
{
    if (enabled)
    {
        Sound s = sounds[game->current_sound_variation];
        if (s.frameCount > 0)
            PlaySound(s);
    }
}

// 查找匹配（2个相邻）
bool find_matches(GameState *game)
{
    bool found = false;
    memset(game->matched_board, 0, sizeof(game->matched_board));

    // 水平匹配
    for (int y = 0; y < BOARD_SIZE; y++)
    {
        for (int x = 0; x < BOARD_SIZE - 1; x++)
        {
            char c = game->board[y][x];
            if (c != ' ' && c == game->board[y][x + 1])
            {
                game->matched_board[y][x] = true;
                game->matched_board[y][x + 1] = true;
                game->score += SCORE_PER_PAIR;
                found = true;
            }
        }
    }

    // 垂直匹配
    for (int x = 0; x < BOARD_SIZE; x++)
    {
        for (int y = 0; y < BOARD_SIZE - 1; y++)
        {
            char c = game->board[y][x];
            if (c != ' ' && c == game->board[y + 1][x])
            {
                game->matched_board[y][x] = true;
                game->matched_board[y + 1][x] = true;
                game->score += SCORE_PER_PAIR;
                found = true;
            }
        }
    }

    return found;
}

// 生成安全的新字符（不会与正下方的字符形成垂直匹配）
char generate_safe_tile(GameState *game, int x, int y)
{
    // 如果是最底部的新字符（y=0时下方无字符，直接返回随机）
    if (y == 0)
        return tile_chars[rand() % TILE_TYPES];

    // 确保新字符与正下方的字符不同（避免垂直匹配）
    char below_char = game->board[y - 1][x]; // 下方已生成的字符
    int attempts = 0;
    char new_char;

    do
    {
        new_char = tile_chars[rand() % TILE_TYPES];
        attempts++;
    } while (new_char == below_char && attempts < MAX_GEN_ATTEMPTS);

    // 防止无限循环（如果多次尝试仍冲突，强制返回不同字符）
    if (new_char == below_char)
    {
        for (int i = 0; i < TILE_TYPES; i++)
        {
            if (tile_chars[i] != below_char)
            {
                new_char = tile_chars[i];
                break;
            }
        }
    }

    return new_char;
}

// 处理匹配（核心修改：控制新字符生成）
void resolve_matches(GameState *game)
{
    // 按列处理下落
    for (int x = 0; x < BOARD_SIZE; x++)
    {
        int write_row = BOARD_SIZE - 1; // 从底部开始

        // 移动非匹配方块向下
        for (int y = BOARD_SIZE - 1; y >= 0; y--)
        {
            if (!game->matched_board[y][x])
            {
                if (y != write_row)
                {
                    game->board[write_row][x] = game->board[y][x];
                    game->fall_offset[write_row][x] = (float)(write_row - y) * TILE_SIZE;
                    game->board[y][x] = ' ';
                }
                write_row--;
            }
        }

        // 顶部生成新字符（核心优化：安全生成，避免初始匹配）
        for (int y = write_row; y >= 0; y--)
        {
            // 生成不会与下方字符冲突的新字符
            game->board[y][x] = generate_safe_tile(game, x, y);
            // 新字符从顶部下落的偏移量
            game->fall_offset[y][x] = (float)(y + 1) * TILE_SIZE;
        }
    }
}

// 预览交换
void preview_swap(GameState *game, int x1, int y1, int x2, int y2)
{
    game->preview_tile = (Vector2){(float)x2, (float)y2};
    game->is_previewing = true;
}

// 取消预览
void cancel_preview(GameState *game)
{
    game->is_previewing = false;
    game->preview_tile = (Vector2){-1, -1};
}

// 处理设置菜单输入
void handle_settings_input(GameState *game)
{
    if (!game->show_settings)
        return;

    Vector2 mouse = GetMousePosition();
    int menu_x = (GetScreenWidth() - MENU_WIDTH) / 2;
    int menu_y = (GetScreenHeight() - MENU_HEIGHT) / 2;

    // 声音开关
    if (CheckCollisionPointRec(mouse, (Rectangle){menu_x, menu_y + 50, MENU_WIDTH, 40}))
    {
        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
        {
            play_sound(game, game->clicks, game->sound_enabled);
            game->sound_enabled = !game->sound_enabled;
        }
    }

    // 切换背景
    if (CheckCollisionPointRec(mouse, (Rectangle){menu_x, menu_y + 100, MENU_WIDTH, 40}))
    {
        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
        {
            play_sound(game, game->clicks, game->sound_enabled);
            game->current_bg = (game->current_bg + 1) % MAX_BACKGROUNDS;
        }
    }

    // 切换音效变体
    if (CheckCollisionPointRec(mouse, (Rectangle){menu_x, menu_y + 150, MENU_WIDTH, 40}))
    {
        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
        {
            play_sound(game, game->clicks, game->sound_enabled);
            game->current_sound_variation = (game->current_sound_variation + 1) % MAX_SOUNDS;
        }
    }

    // 调整最大连锁深度（新增功能）
    if (CheckCollisionPointRec(mouse, (Rectangle){menu_x, menu_y + 200, MENU_WIDTH, 40}))
    {
        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
        {
            play_sound(game, game->clicks, game->sound_enabled);
            game->max_chain_depth = (game->max_chain_depth % 5) + 1; // 1-5级可调
        }
    }

    // 重启游戏
    if (CheckCollisionPointRec(mouse, (Rectangle){menu_x, menu_y + 250, MENU_WIDTH, 40}))
    {
        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
        {
            play_sound(game, game->clicks, game->sound_enabled);
            for (int i = 0; i < MAX_BACKGROUNDS; i++)
                if (game->backgrounds[i].id != 0)
                    UnloadTexture(game->backgrounds[i]);
            for (int i = 0; i < MAX_SOUNDS; i++)
            {
                UnloadSound(game->swaps[i]);
                UnloadSound(game->matches[i]);
                UnloadSound(game->clicks[i]);
            }
            init_game(game, GetScreenWidth(), GetScreenHeight());
            game->show_settings = false;
        }
    }

    // 退出游戏
    if (CheckCollisionPointRec(mouse, (Rectangle){menu_x, menu_y + 300, MENU_WIDTH, 40}))
    {
        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
        {
            play_sound(game, game->clicks, game->sound_enabled);
            // WARNING: GLFW: Error: 65537 Description: The GLFW library is not initialized
            // 段错误
            game->should_exit = true; // Set exit flag
            CloseWindow();
        }
    }

    // 关闭菜单(ESC)
    if (IsKeyPressed(KEY_ESCAPE))
    {
        play_sound(game, game->clicks, game->sound_enabled);
        game->show_settings = false;
    }
}

// 绘制设置菜单（新增连锁深度控制选项）
void draw_settings(GameState *game)
{
    if (!game->show_settings)
        return;

    int menu_x = (GetScreenWidth() - MENU_WIDTH) / 2;
    int menu_y = (GetScreenHeight() - MENU_HEIGHT) / 2;

    // 菜单背景
    DrawRectangleRounded((Rectangle){menu_x, menu_y, MENU_WIDTH, MENU_HEIGHT}, 0.1f, 8, (Color){40, 50, 70, 240});
    DrawRectangleLinesEx((Rectangle){menu_x, menu_y, MENU_WIDTH, MENU_HEIGHT}, 2, (Color){80, 100, 140, 255});

    // 标题
    DrawTextEx(game->game_font, "Settings", (Vector2){menu_x + 80, menu_y + 10}, FONT_SIZE, 1, WHITE);

    // 声音开关
    const char *sound_text = game->sound_enabled ? "Sound: On" : "Sound: Off";
    DrawTextEx(game->game_font, sound_text, (Vector2){menu_x + 20, menu_y + 50}, FONT_SIZE - 4, 1, WHITE);

    // 切换背景
    char bg_text[32];
    sprintf(bg_text, "Background: %d/%d", game->current_bg + 1, MAX_BACKGROUNDS);
    DrawTextEx(game->game_font, bg_text, (Vector2){menu_x + 20, menu_y + 100}, FONT_SIZE - 4, 1, WHITE);

    // 切换音效变体
    char sound_var_text[32];
    sprintf(sound_var_text, "Sound Variant: %d/%d", game->current_sound_variation + 1, MAX_SOUNDS);
    DrawTextEx(game->game_font, sound_var_text, (Vector2){menu_x + 20, menu_y + 150}, FONT_SIZE - 4, 1, WHITE);

    // 连锁深度控制（新增）
    char chain_text[32];
    sprintf(chain_text, "Max Chain Depth: %d", game->max_chain_depth);
    DrawTextEx(game->game_font, chain_text, (Vector2){menu_x + 20, menu_y + 200}, FONT_SIZE - 4, 1, WHITE);

    // 重启选项
    DrawTextEx(game->game_font, "Restart Game", (Vector2){menu_x + 20, menu_y + 250}, FONT_SIZE - 4, 1, WHITE);

    // 退出选项
    DrawTextEx(game->game_font, "Exit Game", (Vector2){menu_x + 20, menu_y + 300}, FONT_SIZE - 4, 1, WHITE);

    // 帮助文本
    DrawTextEx(game->game_font, "Press ESC to close", (Vector2){menu_x + 20, menu_y + 340}, FONT_SIZE - 6, 1, (Color){200, 200, 200, 200});
}

int main(int argc, char **argv)
{
    int screen_width = 1024;
    int screen_height = 768;

    // 处理自定义分辨率
    if (argc == 3)
    {
        int w = atoi(argv[1]), h = atoi(argv[2]);
        if (w >= 1024 && w <= 2560 && h >= 768 && h <= 1600)
        {
            screen_width = w;
            screen_height = h;
        }
    }

    // 初始化窗口和音频
    InitWindow(screen_width, screen_height, "Swap & Match Game");
    InitAudioDevice();
    SetTargetFPS(60);
    srand(time(NULL));
    SetExitKey(0); // 禁用ESC默认退出

    GameState game;
    init_game(&game, screen_width, screen_height);

    // 主游戏循环
    while (!WindowShouldClose() && !game.should_exit)
    {
        // 退格键打开设置
        if (IsKeyPressed(KEY_BACKSPACE))
        {
            play_sound(&game, game.clicks, game.sound_enabled);
            game.show_settings = !game.show_settings;
        }

        // 处理设置菜单
        if (game.show_settings)
        {
            handle_settings_input(&game);
        }
        else
        {
            // 处理棋盘输入
            Vector2 mouse = GetMousePosition();
            if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
            {
                int x = (int)((mouse.x - game.grid_origin.x) / TILE_SIZE);
                int y = (int)((mouse.y - game.grid_origin.y) / TILE_SIZE);

                if (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE)
                {
                    if (game.selected_tile.x == -1)
                    {
                        game.selected_tile = (Vector2){(float)x, (float)y};
                    }
                    else
                    {
                        int prev_x = (int)game.selected_tile.x;
                        int prev_y = (int)game.selected_tile.y;

                        if (x == prev_x && y == prev_y)
                        {
                            cancel_preview(&game);
                            game.selected_tile = (Vector2){-1, -1};
                        }
                        else if ((abs(x - prev_x) == 1 && y == prev_y) ||
                                 (abs(y - prev_y) == 1 && x == prev_x))
                        {
                            if (!game.is_previewing)
                            {
                                preview_swap(&game, prev_x, prev_y, x, y);
                            }
                            else
                            {
                                // 执行交换
                                char temp = game.board[prev_y][prev_x];
                                game.board[prev_y][prev_x] = game.board[y][x];
                                game.board[y][x] = temp;
                                play_sound(&game, game.swaps, game.sound_enabled);

                                // 检查匹配
                                bool has_match = find_matches(&game);
                                if (has_match)
                                {
                                    play_sound(&game, game.matches, game.sound_enabled);
                                    resolve_matches(&game);
                                    game.current_chain_depth = 1; // 重置连锁深度计数
                                }
                                else
                                {
                                    // 无匹配则撤销
                                    char revert = game.board[prev_y][prev_x];
                                    game.board[prev_y][prev_x] = game.board[y][x];
                                    game.board[y][x] = revert;
                                }

                                cancel_preview(&game);
                                game.selected_tile = (Vector2){-1, -1};
                            }
                        }
                        else
                        {
                            cancel_preview(&game);
                            game.selected_tile = (Vector2){(float)x, (float)y};
                        }
                    }
                }
            }
        }

        // 更新下落动画
        for (int y = 0; y < BOARD_SIZE; y++)
        {
            for (int x = 0; x < BOARD_SIZE; x++)
            {
                if (game.fall_offset[y][x] > 0)
                {
                    game.fall_offset[y][x] -= FALL_SPEED;
                    if (game.fall_offset[y][x] < 0)
                        game.fall_offset[y][x] = 0;
                }
            }
        }

        // 处理连锁匹配（新增深度限制）
        bool has_cascade_match;
        do
        {
            has_cascade_match = false;
            // 动画结束且未超过最大连锁深度时才检查
            if (game.fall_offset[0][0] <= 0 && game.current_chain_depth < game.max_chain_depth)
            {
                has_cascade_match = find_matches(&game);
                if (has_cascade_match)
                {
                    play_sound(&game, game.matches, game.sound_enabled);
                    resolve_matches(&game);
                    game.current_chain_depth++; // 增加连锁深度计数
                }
            }
        } while (has_cascade_match);

        // 绘制
        BeginDrawing();
        ClearBackground(BLACK);

        // 绘制背景
        Texture2D current_bg = game.backgrounds[game.current_bg];
        if (current_bg.id != 0)
        {
            DrawTexturePro(current_bg,
                           (Rectangle){0, 0, (float)current_bg.width, (float)current_bg.height},
                           (Rectangle){0, 0, (float)GetScreenWidth(), (float)GetScreenHeight()},
                           (Vector2){0, 0}, 0.0f, WHITE);
        }
        else
        {
            DrawRectangleGradientV(0, 0, GetScreenWidth(), GetScreenHeight(),
                                   (Color){30, 40, 60, 255}, (Color){15, 20, 30, 255});
        }

        // 绘制棋盘
        for (int y = 0; y < BOARD_SIZE; y++)
        {
            for (int x = 0; x < BOARD_SIZE; x++)
            {
                Rectangle tile_rect = {
                    game.grid_origin.x + (x * TILE_SIZE),
                    game.grid_origin.y + (y * TILE_SIZE),
                    (float)TILE_SIZE,
                    (float)TILE_SIZE};

                DrawRectangleRec(tile_rect, (Color){40, 50, 70, 230});
                DrawRectangleLinesEx(tile_rect, 1, (Color){80, 100, 140, 255});

                if (game.board[y][x] != ' ')
                {
                    char text[2] = {game.board[y][x], '\0'};
                    int char_width = MeasureText(text, FONT_SIZE);
                    Vector2 char_pos = {
                        tile_rect.x + (TILE_SIZE - char_width) / 2.0f,
                        tile_rect.y + (TILE_SIZE - FONT_SIZE) / 2.0f - game.fall_offset[y][x]};

                    Color text_color = WHITE;
                    if (game.is_previewing && x == (int)game.preview_tile.x && y == (int)game.preview_tile.y)
                        text_color = YELLOW;
                    else if (game.matched_board[y][x])
                        text_color = GREEN;

                    DrawTextEx(game.game_font, text, char_pos, (float)FONT_SIZE, 1, text_color);
                }
            }
        }

        // 绘制选中边框
        if (game.selected_tile.x != -1)
        {
            Rectangle selected_rect = {
                game.grid_origin.x + ((int)game.selected_tile.x * TILE_SIZE),
                game.grid_origin.y + ((int)game.selected_tile.y * TILE_SIZE),
                (float)TILE_SIZE,
                (float)TILE_SIZE};
            DrawRectangleLinesEx(selected_rect, 2, RED);
        }

        // 绘制分数和连锁深度
        char score_text[32];
        sprintf(score_text, "Score: %d", game.score);
        DrawTextEx(game.game_font, score_text, (Vector2){20, 20}, (float)FONT_SIZE, 1, YELLOW);

        char chain_text[32];
        sprintf(chain_text, "Chain: %d/%d", game.current_chain_depth, game.max_chain_depth);
        DrawTextEx(game.game_font, chain_text, (Vector2){20, 60}, (float)FONT_SIZE - 4, 1, ORANGE);

        // 绘制设置提示
        DrawTextEx(game.game_font, "Press BACKSPACE for Settings",
                   (Vector2){20, GetScreenHeight() - 40}, FONT_SIZE - 4, 1, (Color){200, 200, 200, 200});

        // 绘制设置菜单
        draw_settings(&game);

        EndDrawing();
    }

    // 资源清理
    for (int i = 0; i < MAX_BACKGROUNDS; i++)
        if (game.backgrounds[i].id != 0)
            UnloadTexture(game.backgrounds[i]);
    if (game.game_font.baseSize != GetFontDefault().baseSize)
        UnloadFont(game.game_font);
    for (int i = 0; i < MAX_SOUNDS; i++)
    {
        UnloadSound(game.swaps[i]);
        UnloadSound(game.matches[i]);
        UnloadSound(game.clicks[i]);
    }
    CloseAudioDevice();
    CloseWindow();

    return 0;
}
